#ifndef AVALON_CHANNELADAPTERSERVERCONNECTION_HPP
#define AVALON_CHANNELADAPTERSERVERCONNECTION_HPP
#include <boost/signals2/connection.hpp>
#include "Avalon/IO/ConnectionState.hpp"
#include "Avalon/IO/ServerConnection.hpp"

namespace Avalon {
namespace IO {

  /*! \class ChannelAdapterServerConnection
   *  \brief Adapter class for a ServerConnection requiring a specific Channel.
   *  \author Kamal Mansouri <kranar@hotmail.com>
   */
  class ChannelAdapterServerConnection : public ServerConnection {
    public:

      //! Constructs a ChannelAdapterServerConnection.
      /*!
        \param connection The ServerConnection to wrap.
        \param channelFactory The ChannelFactory to use to build new incoming
                              Channels.
      */
      ChannelAdapterServerConnection(ServerConnection* connection,
        ChannelFactory* channelFactory);

      virtual ~ChannelAdapterServerConnection();

      virtual void Start();

      virtual Threading::Async<Channel*>::Ptr Accept();

      virtual bool IsConnected();

      virtual void Close();

      virtual boost::signals2::connection ConnectClosedSignal(
        const ClosedSignal::slot_type& slot);

      virtual boost::signals2::connection ConnectClosedSignal(
        const ClosedSignal::slot_type& slot, bool* isConnected);

    private:
      boost::recursive_mutex m_mutex;
      boost::scoped_ptr<ServerConnection> m_connection;
      ConnectionState m_connectionState;
      boost::scoped_ptr<ChannelFactory> m_channelFactory;
      boost::condition_variable_any m_closedCondition;
      ClosedSignal m_closedSignal;

      bool InternalIsConnected();
      void WrapResult(const Threading::Async<Channel*>::Ptr& result,
        const Threading::AsyncOwner<Channel*>::Ptr& wrappedChannel);
      void OnAccept(const Threading::Async<Channel*>::Ptr& result,
        const Threading::AsyncOwner<Channel*>::Ptr& wrappedChannel);
      void OnClosed();
  };
}
}

#endif // AVALON_CHANNELADAPTERSERVERCONNECTION_HPP
